﻿using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Blazor;
using System.Reflection;

namespace EasyXaf.BlazorTabbedMdi;

internal sealed class MdiBlazorShowViewStrategy : ShowViewStrategyBase
{
    private readonly ShowViewStrategyBase _blazorShowViewStrategy;

    private MethodInfo _showDialogMethodInfo;
    private MethodInfo _showMessageCoreMethodInfo;
    private MethodInfo _showViewInPopupWindowCoreMethodInfo;

    public MdiBlazorShowViewStrategy(BlazorApplication application)
        : base(application)
    {
        var assembly = typeof(BlazorApplication).Assembly;
        var popupWindowsManagerType = assembly.GetType("DevExpress.ExpressApp.Blazor.Services.IPopupWindowsManager");
        var blazorShowViewStrategyType = assembly.GetType("DevExpress.ExpressApp.Blazor.BlazorShowViewStrategy");
        var popupWindowManager = application.ServiceProvider.GetService(popupWindowsManagerType);
        _blazorShowViewStrategy = (ShowViewStrategyBase)Activator.CreateInstance(blazorShowViewStrategyType, application, popupWindowManager);
    }

    private Window ShowDialog(ShowViewParameters parameters, ShowViewSource showViewSource)
    {
        _showDialogMethodInfo ??= _blazorShowViewStrategy.GetType().GetMethod(nameof(ShowDialog), BindingFlags.NonPublic | BindingFlags.Instance, new Type[] { typeof(ShowViewParameters), typeof(ShowViewSource) });
        return (Window)_showDialogMethodInfo.Invoke(_blazorShowViewStrategy, new object[] { parameters, showViewSource });
    }

    protected override void ShowMessageCore(MessageOptions options)
    {
        _showMessageCoreMethodInfo ??= _blazorShowViewStrategy.GetType().GetMethod(nameof(ShowMessageCore), BindingFlags.NonPublic | BindingFlags.Instance, new Type[] { typeof(MessageOptions) });
        _showMessageCoreMethodInfo.Invoke(_blazorShowViewStrategy, new object[] { options });
    }

    protected override void ShowViewFromCommonView(ShowViewParameters parameters, ShowViewSource showViewSource)
    {
        Application.MainWindow.Template.SetView(parameters.CreatedView);
    }

    protected override void ShowViewFromLookupView(ShowViewParameters parameters, ShowViewSource showViewSource)
    {
        ShowDialog(parameters, showViewSource);
    }

    protected override void ShowViewFromNestedView(ShowViewParameters parameters, ShowViewSource showViewSource)
    {
        ShowDialog(parameters, showViewSource);
    }

    protected override void ShowViewInCurrentWindow(ShowViewParameters parameters, ShowViewSource showViewSource)
    {
        if (showViewSource.SourceFrame is Window window && window.IsMain && window.Template != null)
        {
            window.Template.SetView(parameters.CreatedView);
        }
        else
        {
            showViewSource.SourceFrame.SetView(parameters.CreatedView, showViewSource.SourceFrame);
        }
    }

    protected override void ShowViewInModalWindow(ShowViewParameters parameters, ShowViewSource showViewSource)
    {
        ShowDialog(parameters, showViewSource);
    }

    protected override Window ShowViewInNewWindow(ShowViewParameters parameters, ShowViewSource showViewSource)
    {
        return ShowDialog(parameters, showViewSource);
    }

    protected override void ShowViewInPopupWindowCore(View view, Action okDelegate, Action cancelDelegate, string okButtonCaption, string cancelButtonCaption)
    {
        _showViewInPopupWindowCoreMethodInfo ??= _blazorShowViewStrategy.GetType().GetMethod
        (
            nameof(ShowViewInPopupWindowCore),
            BindingFlags.NonPublic | BindingFlags.Instance,
            new Type[]
            {
                typeof(View), typeof(Action), typeof(Action), typeof(string), typeof(string)
            }
        );

        _showViewInPopupWindowCoreMethodInfo.Invoke(_blazorShowViewStrategy, new object[]
        {
            view, okDelegate, cancelDelegate, okButtonCaption, cancelButtonCaption
        });
    }

    public override void Dispose()
    {
        _blazorShowViewStrategy.Dispose();
        base.Dispose();
    }
}
